// EOEntity.cs
//
//  Copyright (C) 2008 Whitemice Consulting
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//

using System;
using System.Collections;
using System.Collections.Generic;

namespace Whitemice.EOMono
{
  public abstract class EOEntity
  {
    protected string                          name, internalName;
    protected IList<EOFieldDef>               fields;
    protected bool                            magicPrimaryKey;
    protected bool                            readOnly;
    protected ArrayList                       parameters;
    protected string                          alias;
    
    public EOEntity(string name, bool magicPrimaryKey)
      : this(name, magicPrimaryKey, null)
    {
    } // end ctor
    
    public EOEntity(string name, bool magicPrimaryKey, string internalName)
    {
      this.name = name;
      this.internalName = internalName;
      this.magicPrimaryKey = magicPrimaryKey;
      fields = new List<EOFieldDef>();
      this.readOnly = false;
      this.parameters = null;
    } // end ctor
    
    public bool IsAliased
    {
      get { return (internalName == null) ? false : true; }
    }
    
    public bool ReadOnly
    { 
      get { return readOnly; } 
      set { readOnly = value; } 
    } // end ReadOnly
    
    public bool IsReadOny()
    {
      return ReadOnly;
    } // end IsReadOnly
    
    public bool IsWritable()
    {
      return (!(ReadOnly));
    } // end IsWritable
    
    public ArrayList Parameters
    { 
      get 
      {
        if (parameters == null)
          parameters = new ArrayList();
        return parameters; 
      } 
      set { parameters = value; } 
    } // end Parameters
    
    internal string ParametersAsCSV()
    {
      string paramString = string.Empty;
      foreach (object param in Parameters)
      {
        if (paramString.Length > 0)
          paramString = string.Format("{0},", paramString);
        if (param is System.String)
          paramString = string.Format("{0} \'{1}\'", paramString, param.ToString());
        else
          paramString = string.Format("{0} {1}", paramString, param.ToString());
      } // end foreach
      return paramString;
    } // end ParametersAsCSV
    
    public EOFieldDef GetField(string key)
    {
      string k = key.ToLower();
      foreach(EOFieldDef f in fields)
      {
        if((f.Name.ToLower() == k) || 
           ((f.Alias !=null) && (f.Alias.ToLower() == k)))
          return f;
      }
      throw new Exception(string.Format("No such field as {0} in {1}", key, Name));
    } // end GetField
    
    internal string KindOfField(string key)
    {
      return GetField(key).Kind;
    } // end KindOfField
    
    internal object DefaultValue(string key)
    {
      return GetField(key).DefaultValue;
    } // end DefaultValue
    
    public abstract IEORecord NewRecord(IEOConnection _connection);
        
    public string Name 
    { 
      get { return name; } 
    } // end Name
    
    virtual internal string InternalName
    { 
      get { return internalName; } 
    } // end InternalName
    
    public bool MagicPrimaryKey
    { 
      get { return magicPrimaryKey; } 
    } // end MagicPrimaryKey
    
    public void AddField(string name, bool pkey, string kind)
    {
      AddField(name, pkey, kind, null);
    }  // end AddField
    
    public void AddField(string name, bool pkey, string kind, string alias)
    {
      this.AddField(new EOFieldDef(name, kind, pkey, null, alias));
    } // end AddField
    
    public void AddField(EOFieldDef field)
    {
      string     alias = null;
      string     name  = null;
      EOFieldDef f     = null;
            
      name = field.Name.ToLower();
      if (field.Alias != null)
        alias = field.Alias.ToLower();
      foreach(EOFieldDef fd in fields)
      {
        if ((fd.Name == name) ||
            ((fd.Alias != null) && (fd.Alias == alias)))
        {
          f = fd;
          break;
        }
      }
      if (f == null)
      {
        fields.Add(field);
        EOManager.Log.DebugFormat("Added field \"{0}\" to entity \"{1}\"", field.Name, Name);
        if (field.Alias != null)
          EOManager.Log.DebugFormat("Field \"{0}.{1}\" has alias \"{2}\"", Name, field.Name, field.Alias);
      } else EOManager.Log.InfoFormat("Attempt to add duplicate field \"{0}\" to entity \"{1}\"", field.Name, Name);
    } // end AddField
    
    internal string GetFieldsAsCSV()
    {
      string list = string.Empty;
      foreach(EOFieldDef f in fields)
        if (list.Length > 0)
          list = string.Format("{0}, {1}", list, f.Name);
        else
          list = string.Format("{0}", f.Name);
      return list;
    } // end GetFieldsAsCSV
    
    public IList<string> PrimaryKeys
    {
      get
      {
        IList<string> keys = new List<string>();
        foreach(EOFieldDef field in fields)
        {
          if (field.IsPrimaryKey)
            keys.Add(field.Name);
        }
        return keys;
      }
    } // end PrimaryKeys
     
    public bool HasField(string name)
    {
      string x = name.ToLower();
      foreach(EOFieldDef f in fields)
        if ((x == f.Name) || (x == f.Alias))
          return true;
      return false;
    } // end HasField
    
    internal IList<EOFieldDef> Fields
    {
      get
      {
        return fields;
      }
    } // end Fields
    
    public string[] FieldNames
    {
      get
      {
        int      count = 0;
        string[] names = null;
        
        names  = new string[fields.Count];
        foreach(EOFieldDef f in fields)
        {
          names[count] = f.Name;
          count++;
        } // end foreach
        return names;
      } // end get
    } // end FieldNames
  } // end EOEntity
}